package api_sys

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"image"
	"image/jpeg"
	"math"
	"net/http"
	"net/url"
	"os"
	"strings"
	"wrblog-api-go/app/common/token"
	"wrblog-api-go/app/model/model_sys"
	"wrblog-api-go/app/service/service_sys"
	"wrblog-api-go/config"
	"wrblog-api-go/pkg/request"
	"wrblog-api-go/pkg/result"
	"wrblog-api-go/pkg/status"
	"wrblog-api-go/pkg/utils"
)

// @Tags  SysFile - 文件管理
// @Summary  上传文件
// @Accept json
// @Produce json
// @Param Authorization header string true "Authorization"
// @Success 200 {object} result.Result "OK"
// @Router /file/upload [post]
func ApiUpload(c *gin.Context) {
	var sysFile model_sys.SysFilePo
	fileHeader, err := c.FormFile("file")
	uploadType := c.PostForm("uploadType")
	if err == nil {
		fileSize := fileHeader.Size
		if fileHeader.Size > int64(config.Conf.ConfigInfo.FileMaxSize<<20) {
			result.Wrap(status.BadRequest, fmt.Sprintf("文件大小不能超过%dMB", config.Conf.ConfigInfo.FileMaxSize)).Json(c)
			return
		}
		fileType, oldFileName, suffix := utils.GetFileInfo(fileHeader)
		newFileName := fmt.Sprintf("%s-%d%s", oldFileName[:len(oldFileName)-len(suffix)], utils.GetNow().Unix(), suffix)
		newFilePath := fmt.Sprintf("/%s/%s", utils.GetNowDay(), newFileName)
		err = c.SaveUploadedFile(fileHeader, fmt.Sprintf("%s%s", config.Conf.ConfigInfo.Profile, newFilePath))
		absolutePath := config.Conf.ConfigInfo.Profile + newFilePath
		if err == nil {
			size := float64(fileSize) / float64(1024) / float64(1024)
			sysFile, err = service_sys.AddFile(model_sys.SysFilePo{
				SysFile: model_sys.SysFile{
					FileType:     fileType,
					FileSize:     math.Round(size*100) / 100,
					PreImg:       utils.GetFilePreImg(fileType, absolutePath),
					OldName:      oldFileName,
					UploadType:   uploadType,
					NewName:      newFileName,
					FileSuffix:   suffix,
					RelativePath: config.Conf.ConfigInfo.FilePrefix + newFilePath,
					AbsolutePath: absolutePath,
					CreateBy:     token.GetUk(c),
					UserId:       token.GetUserId(c),
				},
			})
		}
	}
	result.Res(sysFile, err).Json(c)
}

// @Tags  SysFile - 文件管理
// @Summary  文件列表
// @Accept json
// @Produce json
// @Param Authorization header string true "Authorization"
// @Param sysFile query model_sys.SelectSysFile true "sysFile"
// @Success 200 {object} result.Result "OK"
// @Router /file/list [get]
func ApiFileList(c *gin.Context) {
	raw, _ := c.Get(request.BindObj)
	sysFile := raw.(model_sys.SelectSysFile)
	sysFile.UploadType = "yellow"
	result.PageRes(service_sys.GetList(sysFile)).Json(c)
}

// @Tags  SysFile - 文件管理
// @Summary  所有图片id
// @Accept json
// @Produce json
// @Param Authorization header string true "Authorization"
// @Param sysFile query model_sys.SelectSysFile true "sysFile"
// @Success 200 {object} result.Result "OK"
// @Router /file/listIdAll [get]
func ApiFileIdAll(c *gin.Context) {
	raw, _ := c.Get(request.BindObj)
	sysFile := raw.(model_sys.SelectSysFile)
	sysFile.UploadType = "yellow"
	sysFile.FileType = "image"
	result.Res(service_sys.GetListIdAll(sysFile)).Json(c)
}

// @Tags  SysFile - 文件管理
// @Summary  获取文件预览
// @Accept json
// @Produce json
// @Param Authorization header string true "Authorization"
// @Param fileId path int true "fileId"
// @Success 200 {object} result.Result "OK"
// @Router /file/preview/{fileId} [get]
func ApiPreviewFile(c *gin.Context) {
	fileId := c.Param("fileId")
	if fileId == "" {
		result.Wrap(status.BadRequest, "参数读取失败").Json(c)
	} else {
		sysFile, err := service_sys.GetFileById(fileId)
		if err != nil {
			result.Fail(err)
		} else {
			if _, err := os.Stat(sysFile.PreImg); os.IsNotExist(err) {
				result.Ok(nil)
				return
			}
			// 打开图片文件
			file, err := os.Open(sysFile.PreImg)
			if err != nil {
				result.Fail(err)
				return
			}
			defer file.Close()

			// 解码图片
			img, _, err := image.Decode(file)
			if err != nil {
				result.Fail(fmt.Errorf("无法解码图片: %v", err))
				return
			}

			// 设置响应头
			c.Header("Content-Type", sysFile.FileType) // 可根据需要动态设置
			c.Status(status.OK)
			// 压缩并写入响应体
			var opt jpeg.Options
			if sysFile.FileSize > 5 {
				opt.Quality = 50 // 压缩质量：1-100，值越小压缩越强，体积越小
			} else if sysFile.FileSize > 2 {
				opt.Quality = 30 // 压缩质量：1-100，值越小压缩越强，体积越小
			}
			if err := jpeg.Encode(c.Writer, img, &opt); err != nil {
				result.Fail(fmt.Errorf("图片压缩失败: %v", err))
				return
			}
		}
	}
}

// @Tags  SysFile - 文件管理
// @Summary  获取文件内容
// @Accept json
// @Produce json
// @Param Authorization header string true "Authorization"
// @Param fileId path int true "fileId"
// @Success 200 {object} result.Result "OK"
// @Router /file/info/{fileId} [get]
func ApiInfoFile(c *gin.Context) {
	fileId := c.Param("fileId")
	if fileId == "" {
		result.Wrap(status.BadRequest, "参数读取失败").Json(c)
	} else {
		sysFile, err := service_sys.GetFileById(fileId)
		if err != nil {
			result.Fail(err)
		} else {
			//if _, err = os.Stat(sysFile.AbsolutePath); os.IsNotExist(err) {
			//	result.Fail(err)
			//	return
			//}
			if strings.HasPrefix(sysFile.FileType, "video/") {
				// 打开文件
				file, err := os.Open(sysFile.AbsolutePath)
				if err != nil {
					result.Fail(err)
					return
				}
				defer file.Close()
				// 获取文件信息
				fileInfo, err := file.Stat()
				if err != nil {
					result.Fail(err)
					return
				}
				// 支持懒加载（Range 请求）
				c.Header("Content-Type", sysFile.FileType)
				c.Header("X-File-Name", url.QueryEscape(sysFile.OldName))
				c.Header("Access-Control-Expose-Headers", "X-File-Name")
				// 使用 ServeContent 支持断点续传
				http.ServeContent(c.Writer, c.Request, sysFile.OldName, fileInfo.ModTime(), file)
			} else {
				// 设置响应头并直接返回文件
				c.Header("Content-Type", sysFile.FileType)                // 你也可以自己识别 MIME 类型更准确
				c.Header("X-File-Name", url.QueryEscape(sysFile.OldName)) // 自定义头传递文件名
				c.Header("Access-Control-Expose-Headers", "X-File-Name")
				c.File(sysFile.AbsolutePath)
			}
		}
	}
}

// @Tags  SysFile - 文件管理
// @Summary  修改文件
// @Accept json
// @Produce json
// @Param Authorization header string true "Authorization"
// @Param sysFile body model_sys.SysFile true "sysFile"
// @Success 200 {object} result.Result "OK"
// @Router /file/edit [put]
func ApiFileEdit(c *gin.Context) {
	raw, _ := c.Get(request.BindObj)
	sysFilePo := raw.(model_sys.SysFilePo)
	i, err := service_sys.EditFile(sysFilePo)
	result.Res(i, err).Json(c)
}

// @Tags  SysFile - 文件管理
// @Summary  删除文件[实体删除]
// @Accept json
// @Produce json
// @Param Authorization header string true "Authorization"
// @Param fileIds query string true "fileIds"
// @Success 200 {object} result.Result "OK"
// @Router /file/removes [delete]
func ApiFileRemoves(c *gin.Context) {
	fileIds := c.Query("fileIds")
	i, err := service_sys.RemoveSysFile(fileIds)
	result.Res(i, err).Json(c)
}
